package com.ruoyi.common.utils;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


/**
 * 本地缓存方式
 */
@SuppressWarnings(value = {"unchecked"})
@Component
public class Localcache {

    private Map<String, Object> persistentCache;

    /**
     * token认证cache - 会自动过期的map
     */
    private Cache<String, Object> tokenCache;

    /**
     * 防止重复提交
     */
    private Cache<String, Object> repeatSubmitCache;

    /**
     * 验证码服务
     */
    private Cache<String, Object> captchaCache;

    @PostConstruct
    public void init() {

        persistentCache = new ConcurrentHashMap<>(1024);

        tokenCache = CacheBuilder.newBuilder()
                .expireAfterAccess(30, TimeUnit.MINUTES) // 基于访问的过期：在最后一次访问30分钟后过期
                .maximumSize(1000) // 缓存最多存储1000个项
                .build();


        repeatSubmitCache = CacheBuilder.newBuilder()
                .expireAfterWrite(5000, TimeUnit.MILLISECONDS) // 缓存项在写入5s后过期
                .maximumSize(1000) // 缓存最多存储1000个项
                .build();

        captchaCache = CacheBuilder.newBuilder()
                .expireAfterWrite(1, TimeUnit.MINUTES) // 缓存项在写入1分钟后过期
                .maximumSize(1000) // 缓存最多存储1000个项
                .build();
    }

    /**
     * Get方法, 转换结果类型并屏蔽异常, 仅返回Null.
     */
    public <T> T get(String key) {
        try {
            Object obj = persistentCache.get(key);

            if (null == obj) {
                obj = tokenCache.getIfPresent(key);
            }

            if (null == obj) {
                obj = captchaCache.getIfPresent(key);
            }

            if (null == obj) {
                obj = repeatSubmitCache.getIfPresent(key);
            }

            return (T) obj;
        } catch (RuntimeException e) {

            return (T) null;
        }
    }

    public List<String> keys(String key) {
        List<String> keyList = new ArrayList<String>();
        List<String> keys = new ArrayList<String>(persistentCache.keySet());
        for (int i = 0; i < keys.size(); i++) {
            if (keys.get(i).startsWith(key)) {
                keyList.add(keys.get(i));
            }
        }
        return keyList;
    }

    /**
     * 异步Set方法, 不考虑执行结果.
     *
     * @param key
     * @param value
     * @param expiredTime 单位：秒
     */
    public void set(String key, Object value, int expiredTime) {
        if (0 == expiredTime) {
            persistentCache.put(key, value);
        } else if (expiredTime <= 60) {        //TTL少于1分钟
            repeatSubmitCache.put(key, value);
        } else if (expiredTime <= 300) {    //TTL少于5分钟
            captchaCache.put(key, value);
        } else {
            tokenCache.put(key, value);
        }
    }


    /**
     * 持久化保存
     *
     * @param key
     * @param value
     */
    public void set(String key, Object value) {
        try {
            this.set(key, value, 0);
        } catch (Exception e) {

        }
    }

    /**
     * 异步 Delete方法, 不考虑执行结果.
     */
    public void delete(final String key) {
        persistentCache.remove(key);
        captchaCache.invalidate(key);
        tokenCache.invalidate(key);
        //防止重复提交和token过期，不存在删除的方法
    }

    public void delete(final Collection<String> keys) {
        for (String key : keys) {
            delete(key);
        }
    }

}
